package com.sunyard.manage.controller;

import com.alibaba.fastjson.JSON;
import com.sunyard.constant.ErrMessageConst;
import com.sunyard.dal.bo.*;
import com.sunyard.dal.bo.operator.*;
import com.sunyard.dal.bo.sys.*;
import com.sunyard.dal.entity.Operator;
import com.sunyard.dal.entity.suzhou.WarnVo;
import com.sunyard.dal.mapper.OperatorMapper;
import com.sunyard.dal.mapper.RoleMapper;
import com.sunyard.dal.vo.inspect.PcInspect;
import com.sunyard.manage.service.OperatorLogService;
import com.sunyard.manage.service.OperatorService;
import com.sunyard.manage.util.ValidatorUtils;
import com.sunyard.utils.ExcelOutput;
import com.sunyard.utils.Response.BaseResult;
import com.sunyard.utils.Response.GetResult;
import com.sunyard.utils.Response.HeaderResult;
import com.sunyard.utils.TokenUtil;
import com.sunyard.utils.manage.DataGrid;
import com.sunyard.utils.sm2.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.toList;

/**
 * @author jiy.fang
 * @ClassName 用户管理控制器
 * @Description description
 * @date 2019/7/23 0:05
 */

@Slf4j
@Api(tags = "OperatorController", description = "用户管理")
@RestController
@RequestMapping(value = "/operator", method = RequestMethod.POST)
public class OperatorController {

    @Autowired
    private OperatorService operatorService;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private OperatorMapper operatorMapper;

    @Autowired
    private OperatorLogService operatorLogService;
    /**
     * 超级管理员
     */
    @Value("${admin.name}")
    private String adminName;
    /**
     * 超级审核员
     */
    @Value("${auditor.name}")
    private String auditorName;

    @Value("${operator.role.id}")
    private String adminRole;

    /**
     * @Description: 分页查询用户信息
     * @Author: jiy.fang
     * @Date: 2019/7/23 9:49
     */
    @RequestMapping("/queryOperator")
    @ResponseBody
    @ApiOperation("分页查询用户信息")
    public BaseResult<DataGrid<Operator>> getOperatorByPage(HttpServletRequest request, @RequestBody PaginationBO<OperatorQueryBO> queryBO) throws Exception {
        return operatorService.queryOrganizationByPage(request, queryBO);
    }

    /**
     * @Description: 查询用户预警信息
     * @Author: tsz
     * @Date: 2019/7/23 9:49
     */
    @RequestMapping("/queryOperatorWarn")
    @ResponseBody
    @ApiOperation("分页查询用户信息")
    public BaseResult<DataGrid<WarnVo>> queryOperatorWarn(HttpServletRequest request, @RequestBody PaginationBO<OperatorQueryBO> queryBO) throws Exception {
        return operatorService.queryOperatorWarn(request, queryBO);
    }

    /**
     * @Description: 添加用户信息
     * @Author: jiy.fang
     * @Date: 2019/7/23 10:13
     */
    @RequestMapping(value = "/addOperator")
    @ResponseBody
    @ApiOperation("添加用户信息")
    public BaseResult insertOperator(HttpServletRequest request, @Valid @RequestBody OperatorAddBO operatorAddBO) throws Exception {
        return operatorService.insertOperator(request, operatorAddBO);
    }

    /**
     * @Description: 修改用户信息
     * @Author: jiy.fang
     * @Date: 2019/7/23 18:46
     */
    @RequestMapping(value = "/updateOperator")
    @ResponseBody
    @ApiOperation("修改用户信息")
    public BaseResult updateOperator(HttpServletRequest request, @Valid @RequestBody OperatorUpdateBO operatorUpdateBO) throws Exception {
        return operatorService.updateOperator(request, operatorUpdateBO);
    }

    /**
     * @Description: 删除用户
     * @Author: jiy.fang
     * @Date: 2019/7/23 19:36
     */
    @RequestMapping(value = "/deleteOperator")
    @ResponseBody
    @ApiOperation("删除用户")
    public BaseResult deleteOperator(HttpServletRequest request, @Valid @RequestBody OperatorDeleteBO operatorDeleteBO) throws Exception {
        return operatorService.deleteOperator(request, operatorDeleteBO);
    }

    /**
     * @Description: 批量删除用户
     * @Author: jiy.fang
     * @Date: 2019/7/23 19:36
     */
    @RequestMapping(value = "/batchDeleteOperator")
    @ResponseBody
    @ApiOperation("批量删除用户")
    public BaseResult batchDeleteOperator(HttpServletRequest request, @Valid @RequestBody OperatorDeleteBO operatorDeleteBO) throws Exception {
        return operatorService.batchDeleteOperator(request, operatorDeleteBO);
    }

    /**
     * @Description: 重置密码
     * @Author: jiy.fang
     * @Date: 2019/7/23 19:22
     */
    @ApiOperation("重置密码")
    @RequestMapping(value = "/resetPwd")
    @ResponseBody
    public BaseResult resetPwd(HttpServletRequest request, @Valid @RequestBody ResetPasswordBO resetPasswordBO) throws Exception {
        return operatorService.resetPwd(request, resetPasswordBO);
    }

    /**
     * 重置初始化密码
     * @param request
     * @param resetInitPasswordBO
     * @return
     * @throws Exception
     */
    @ApiOperation("重置初始化密码")
    @RequestMapping(value = "/resetInitPwd")
    @ResponseBody
    public BaseResult resetInitPwd(HttpServletRequest request, @Valid @RequestBody ResetInitPasswordBO resetInitPasswordBO) throws Exception {
        return operatorService.resetInitPwd(request, resetInitPasswordBO);
    }

    /**
     * @Description: 批量重置密码
     * @Author: jiy.fang
     * @Date: 2019/7/23 19:22
     */
    @ApiOperation("批量重置密码")
    @RequestMapping(value = "/batchResetPwd")
    @ResponseBody
    public BaseResult batchResetPwd(HttpServletRequest request, @Valid @RequestBody ResetPasswordBO resetPasswordBO) throws Exception {
        return operatorService.batchResetPwd(request, resetPasswordBO);
    }

    /**
     * @Description: 登录解锁
     * @Author: jiy.fang
     * @Date: 2019/7/23 20:03
     */
    @ApiOperation("登录解锁")
    @RequestMapping(value = "/unlock")
    @ResponseBody
    public BaseResult unlockOperator(HttpServletRequest request, @Valid @RequestBody UnlockOperatorBO unlockOperatorBO) throws Exception {
        return operatorService.unlockOperator(request, unlockOperatorBO);
    }

    /**
     * @Description: 批量登录解锁
     * @Author: jiy.fang
     * @Date: 2019/7/23 20:03
     */
    @ApiOperation("批量登录解锁")
    @RequestMapping(value = "/batchUnlock")
    @ResponseBody
    public BaseResult batchUnlock(HttpServletRequest request, @Valid @RequestBody UnlockOperatorBO unlockOperatorBO) throws Exception {
        return operatorService.batchUnlock(request, unlockOperatorBO);
    }

    /**
     * @Description: 用户启用
     * @Author: jiy.fang
     * @Date: 2019/7/23 20:15
     */
    @ApiOperation("用户启用")
    @RequestMapping(value = "/enable")
    @ResponseBody
    public BaseResult enableOperator(HttpServletRequest request, @Valid @RequestBody EnableOperatorBO enableOperatorBO) throws Exception {
        return operatorService.enableOperator(request, enableOperatorBO);
    }

    /**
     * @Description: 用户批量启用
     * @Author: jiy.fang
     * @Date: 2019/7/23 20:15
     */
    @ApiOperation("用户批量启用")
    @RequestMapping(value = "/batchEnable")
    @ResponseBody
    public BaseResult batchEnable(HttpServletRequest request, @Valid @RequestBody EnableOperatorBO enableOperatorBO) throws Exception {
        return operatorService.batchEnable(request, enableOperatorBO);
    }

    /**
     * @Description: 用户停用
     * @Author: jiy.fang
     * @Date: 2019/7/23 20:30
     */
    @ApiOperation("用户停用")
    @RequestMapping(value = "/disable")
    @ResponseBody
    public BaseResult disableOperator(HttpServletRequest request, @Valid @RequestBody DisableOperatorBO disableOperatorBO) throws Exception {
        return operatorService.disableOperator(request, disableOperatorBO);
    }

    /**
     * @Description: 用户批量停用
     * @Author: jiy.fang
     * @Date: 2019/7/23 20:30
     */
    @ApiOperation("用户批量停用")
    @RequestMapping(value = "/batchDisable")
    @ResponseBody
    public BaseResult batchDisable(HttpServletRequest request, @Valid @RequestBody DisableOperatorBO disableOperatorBO) throws Exception {
        return operatorService.batchDisable(request, disableOperatorBO);
    }

    /**
     * @Description: 用户导出
     * @Author: jiy.fang
     * @Date: 2019/7/23 21:10
     */
    @ApiOperation("用户导出")
    @RequestMapping(value = "/export")
    @ResponseBody
    public void exportOperator(HttpServletResponse response, @RequestBody PaginationBO<OperatorQueryBO> queryBO, HttpServletRequest request) {
        try {
            OperatorQueryBO operatorQueryBO = queryBO.getParams();
            log.info("用户信息导出入参：{}", JSON.toJSONString(operatorQueryBO));
            String orgId = TokenUtil.getOrgId(request.getHeader("token"));
            String opId = TokenUtil.getOpId(request.getHeader("token"));
            String opName = TokenUtil.getOpName(request.getHeader("token"));
            operatorLogService.insert("用户信息导出", "用户导出", "1", opId, opName, orgId);
            if (StringUtils.isNotBlank(operatorQueryBO.getOrgId())) {
                orgId = operatorQueryBO.getOrgId();
            }
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("opName", operatorQueryBO.getOpName());
            queryMap.put("opRealname", operatorQueryBO.getOpRealname());
            queryMap.put("roleId", operatorQueryBO.getRoleId());
            queryMap.put("opStatus", operatorQueryBO.getOpStatus());
            queryMap.put("adminName", adminName);
            queryMap.put("adminRole", adminRole);
            queryMap.put("auditorName", auditorName);
            List<String> orgIds = new ArrayList<>();
            //获取当前机构及下属机构id集合
            if (operatorQueryBO.getOrgId() == null || "".equals(operatorQueryBO.getOrgId())) {
                orgIds = operatorService.getListOrgIds(orgId);
                orgIds.add(orgId);
                queryMap.put("list", orgIds);
            } else {
                orgIds.add(operatorQueryBO.getOrgId());
                queryMap.put("list", orgIds);
            }
            //执行查询
            List<Operator> operatorList = operatorMapper.getListOperatorByPage(queryMap);
            if (operatorList == null || operatorList.size() <= 0) {
                throw new RuntimeException("无数据无需导出");
            }
            String title = "用户信息导出" + Math.random() + ".xls";
            String[] headers = new String[]{"用户名", "姓名", "所属机构", "机构名称", "角色编码", "角色名称", "身份证号", "状态", "登录类型", "是否有审核权限"};

            List<Object[]> dataList;
            String[] opStatusArr = {"启用", "停用", "注销", "锁定"};
            dataList = operatorList.stream().map(operator -> {
                Object[] obj = new Object[headers.length];
                obj[0] = operator.getOpName();
                obj[1] = operator.getOpRealname();
                obj[2] = operator.getOrgId();
                obj[3] = operator.getOrgName();
                obj[4] = operator.getRoleId();
                obj[5] = operator.getRoleName();
                obj[6] = operator.getIdCard();
                obj[7] = opStatusArr[operator.getOpStatus()];
                String loginType;
                if ("1".equals(operator.getLoginType())) {
                    loginType = "密码";
                } else {
                    loginType = "指纹";
                }
                obj[8] = loginType;
                String auditPermission;
                if ("0".equals(operator.getAuditPermission())) {
                    auditPermission = "否";
                } else {
                    auditPermission = "是";
                }
                obj[9] = auditPermission;
                return obj;
            }).collect(toList());

            OutputStream out = null;
            // 防止中文乱码
            String headStr = "attachment; filename=\"" + new String(title.getBytes("gb2312"), "ISO8859-1") + "\"";
            response.setContentType("octets/stream");
            response.setContentType("APPLICATION/OCTET-STREAM");
            response.setHeader("Content-Disposition", headStr);
            out = response.getOutputStream();
            ExcelOutput ex = new ExcelOutput(title, headers, dataList);
            ex.export(out);
            log.info("用户信息导出");

        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            HeaderResult.setFailHeader(request, response, e.getMessage());
        }
    }

    /**
     * 下载导入模板xls
     */
    @ApiOperation("下载导入模板xls")
    @PostMapping("/downloadTem")
    public void downloadTem(HttpServletResponse response) {

        String[] headers = new String[]{"用户编号", "用户姓名", "所属机构号", "角色名称", "登录类型（1-密码 2-指纹）"};
        List<Object[]> dataList = null;
        // 防止中文乱码
        String headStr = null;
        OutputStream out = null;
        try {
            headStr = "attachment; filename=\"" + new String("customerMangerTemplate.xls".getBytes("utf8"), "ISO8859-1") + "\"";
            response.setContentType("octets/stream");
            response.setContentType("APPLICATION/OCTET-STREAM");
            response.setHeader("Content-Disposition", headStr);
            out = response.getOutputStream();
            ExcelOutput ex = new ExcelOutput("customerMangerTemplate.xls", headers, dataList);
            ex.export(out);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 用户批量导入
     *
     * @param multipartFile addBO
     * @return
     * @throws Exception
     */
    @ApiOperation("导入用户管理信息")
    @PostMapping("/operatorImport")
    public BaseResult importOperatorInfo(HttpServletRequest request, OperatorAddBO addBO,
                                         @RequestParam("multipartFile") MultipartFile multipartFile) throws Exception {
        try {
            String suffix = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf("."));
            if (".xls".equals(suffix) || ".xlsx".equals(suffix)) {
                InputStream inputStream = multipartFile.getInputStream();
                HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
//                XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
                HSSFSheet sheet = workbook.getSheetAt(0);
                if (sheet != null) {
                    // getLastCellNum比列标大1,行标&列标都以0开始。
                    List<OperatorAddBO> addBOList = new ArrayList<>();
                    System.out.println(sheet.getLastRowNum() + "==============");
                    for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                        // 从第二行开始得到每行的值
                        HSSFRow row = sheet.getRow(i);
                        OperatorAddBO operatorAddBO = new OperatorAddBO();
                        row.getCell(0).setCellType(CellType.STRING);
                        String opName = row.getCell(0).getStringCellValue();
                        row.getCell(1).setCellType(CellType.STRING);
                        String opRealname = row.getCell(1).getStringCellValue();
                        row.getCell(2).setCellType(CellType.STRING);
                        String orgId = row.getCell(2).getStringCellValue();
                        row.getCell(3).setCellType(CellType.STRING);
                        String roleName = row.getCell(3).getStringCellValue();
                        row.getCell(4).setCellType(CellType.STRING);
                        String loginType = row.getCell(4).getStringCellValue();
                        //通过角色名称查询角色ID
                        String roleId = roleMapper.getRoleByRoleName(roleName);
                        operatorAddBO.setRoleId(roleId);
                        //row.getCell(5).setCellType(CellType.STRING);
                        //String loginType = row.getCell(5).getStringCellValue();
                        //赋值
                        operatorAddBO.setOpName(opName);
                        operatorAddBO.setOpRealname(opRealname);
                        //operatorAddBO.setOpTel(tel);
                        operatorAddBO.setOrgId(orgId);
                        operatorAddBO.setLoginType(loginType);
                        operatorAddBO.setRoleName(roleName);
                        operatorAddBO.setAuditor(addBO.getAuditor());
                        System.out.println("========" + operatorAddBO + "==========");
                        addBOList.add(operatorAddBO);
                    }
                    int flag = 0;
                    String msg = null;
                    for (int i = 0; i < addBOList.size(); i++) {
                        try {
                            ValidatorUtils.beanValidate(addBOList.get(i));
                            if (StringUtils.isBlank(addBOList.get(i).getRoleName())){
                                throw new IllegalArgumentException("所属角色名称不能为空");
                            }
                            BaseResult baseResult = operatorService.insertOperatorByImport(request, addBOList.get(i), addBOList.get(i).getRoleName());
                            if (!"00".equals(baseResult.getDataCode())) {
                                log.info("用户导入错误信息={}", baseResult.getDataMessage());
                                flag++;
                                if (StringUtil.isEmpty(msg)) {
                                    msg = String.valueOf(i + 1);
                                } else {
                                    msg = msg + "," + (i + 1);
                                }
                            }
                        } catch (Exception e) {
                            log.info("用户信息导入错误信息={}", e.getMessage());
                            flag++;
                            if (StringUtil.isEmpty(msg)) {
                                msg = String.valueOf(i + 1);
                            } else {
                                msg = msg + "," + (i + 1);
                            }
                        }
                    }
                    if (flag == 0) {
                        return GetResult.getResultSuccess("用户导入成功");
                    } else {
                        return GetResult.getResultFail("第" + msg + "条数据错误，用户导入失败");
                    }
                }
                return GetResult.getResultSuccess("用户导入失败");
            } else{
                return GetResult.getResultFail("文件类型只支持.xls 与.xlsx");
            }
        } catch (IOException e) {
            e.printStackTrace();
            return GetResult.getResultFail("用户导入失败");
        }
    }

    /**
     * @Description: 同步审核验证密码
     * @Author: chengy.wei
     * @Date: 2022/06/29
     */
    @ApiOperation("同步审核验证密码")
    @PostMapping(value = "/auditPassword")
    @ResponseBody
    public BaseResult<List<PcInspect>> auditPassword(HttpServletResponse response, HttpServletRequest request,
                                                     @Valid @RequestBody AuditPasswordBo auditPasswordBo) throws Exception {
        return operatorService.auditPassword(auditPasswordBo);
    }

    /**
     * @Description 根据当前登录账号 所属机构的角色查询 当前机构同等角色的用户 以及上一级 机构的同等角色的用户
     * @Author: chengy.wei
     * @Date: 2022/06/29
     */
    @ApiOperation(value = "获取当前机构同等角色 和上一级机构同等角色的用户")
    @RequestMapping(value = "/getOperatorListByRoleOrg")
    @ResponseBody
    public BaseResult<List<Operator>> getOperatorListByRoleOrg(HttpServletRequest request, @RequestBody OperatorQueryBO operatorQueryBO) {
        try {
            return operatorService.getOperatorListByRoleOrg(request, operatorQueryBO);
        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            return GetResult.getResultErr();
        }
    }

    /**
     * @Description: 转授权
     * @Author: chengy.wei
     * @Date: 2022/06/29
     */
    @ApiOperation("转授权")
    @RequestMapping(value = "/updateAuthority")
    @ResponseBody
    public BaseResult updateAuthority(HttpServletRequest request, @Valid @RequestBody AuthorityUpdateBo authorityUpdateBo) throws Exception {
        return operatorService.updateAuthority(request, authorityUpdateBo);
    }

    /**
     * @Description: 授权回退
     * @Author: chengy.wei
     * @Date: 2022/06/29
     */
    @ApiOperation("授权回退")
    @RequestMapping(value = "/rollBackAuthority")
    @ResponseBody
    public BaseResult rollBackAuthority(HttpServletRequest request, @Valid @RequestBody AuthorityUpdateBo authorityUpdateBo) throws Exception {
        return operatorService.rollBackAuthority(request, authorityUpdateBo);
    }
}
